<!DOCTYPE HTML>
<html lang="zh-Hans" class="sidebar-visible no-js light">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>数据库表达式执行的黑魔法：用HRTB写bound Part 2 - Rust 优秀博文</title>


        <!-- Custom HTML head -->
        
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        <link rel="icon" href="../../favicon.svg">
        <link rel="shortcut icon" href="../../favicon.png">
        <link rel="stylesheet" href="../../css/variables.css">
        <link rel="stylesheet" href="../../css/general.css">
        <link rel="stylesheet" href="../../css/chrome.css">
        <link rel="stylesheet" href="../../css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="../../FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="../../fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../../highlight.css">
        <link rel="stylesheet" href="../../tomorrow-night.css">
        <link rel="stylesheet" href="../../ayu-highlight.css">

        <!-- Custom theme stylesheets -->

    </head>
    <body>
        <!-- Provide site root to javascript -->
        <script type="text/javascript">
            var path_to_root = "../../";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add('js');
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">1.</strong> 类型系统</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../01_类型系统/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow.html"><strong aria-hidden="true">1.1.</strong> Rust Concept Clarification Deref vs AsRef vs Borrow vs Cow</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust_Concept_Clarification_Deref_vs_AsRef_vs_Borrow_vs_Cow/Deref_AsRef_Borrow_Cow释义.html"><strong aria-hidden="true">1.2.</strong> Deref AsRef Borrow Cow 释义</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然/Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然.html"><strong aria-hidden="true">1.3.</strong> Rust的Borrow和AsRef：让你的代码用起来像呼吸一样自然</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust的Cow类型有什么用？详解Cow及其用途/Rust的Cow类型有什么用？详解Cow及其用途.html"><strong aria-hidden="true">1.4.</strong> Rust的Cow类型有什么用？详解Cow及其用途</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/判别Fn、FnMut、FnOnce的标准/判别Fn、FnMut、FnOnce的标准.html"><strong aria-hidden="true">1.5.</strong> 判别Fn、FnMut、FnOnce的标准</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/一行代码告诉你内部可变性的真相(UnsafeCell)/一行代码告诉你内部可变性的真相(UnsafeCell).html"><strong aria-hidden="true">1.6.</strong> 一行代码告诉你内部可变性的真相(UnsafeCell)</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Tour_of_Rust's_Standard_Library_Traits/Tour_of_Rust's_Standard_Library_Traits.html"><strong aria-hidden="true">1.7.</strong> Tour of Rust's Standard Library Traits</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/逆变、协变与子类型，以及Rust/逆变、协变与子类型，以及Rust.html"><strong aria-hidden="true">1.8.</strong> 逆变、协变与子类型，以及Rust</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust自引用结构、Pin与Unpin/Rust自引用结构、Pin与Unpin.html"><strong aria-hidden="true">1.9.</strong> Rust自引用结构、Pin与Unpin</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/为什么Rust需要Pin,Unpin/为什么Rust需要Pin,Unpin.html"><strong aria-hidden="true">1.10.</strong> 译：为什么 Rust 需要 Pin, Unpin ？</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/定海神针Pin和Unpin/定海神针Pin和Unpin.html"><strong aria-hidden="true">1.11.</strong> 译：定海神针 Pin 和 Unpin</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/sizedness-in-rust/sizedness-in-rust.html"><strong aria-hidden="true">1.12.</strong> Sizedness in Rust</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/Rust生命周期集大成者PhantomData〈T〉/Rust生命周期集大成者PhantomData〈T〉.html"><strong aria-hidden="true">1.13.</strong> Rust生命周期集大成者 PhantomData&lt;T&gt;</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用Rust做类型体操_Part_0.html"><strong aria-hidden="true">1.14.</strong> 数据库表达式执行的黑魔法：用Rust做类型体操 Part 0</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：GAT实现引用类型关联_Part_1.html"><strong aria-hidden="true">1.15.</strong> 数据库表达式执行的黑魔法：GAT实现引用类型关联 Part 1</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用HRTB写bound_Part_2.html" class="active"><strong aria-hidden="true">1.16.</strong> 数据库表达式执行的黑魔法：用HRTB写bound Part 2</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用Rust做类型体操之用宏展开重复代码_Part_3_&_4.html"><strong aria-hidden="true">1.17.</strong> 数据库表达式执行的黑魔法：用Rust做类型体操之用宏展开重复代码 Part 3 & 4</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：与Rust编译器斗智斗勇之表达式向量化_Part_5_&_6.html"><strong aria-hidden="true">1.18.</strong> 数据库表达式执行的黑魔法：与Rust编译器斗智斗勇之表达式向量化 Part 5 & 6</a></li><li class="chapter-item expanded "><a href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：在Rust中用宏关联逻辑类型和实际类型_Part_7.html"><strong aria-hidden="true">1.19.</strong> 数据库表达式执行的黑魔法：在Rust中用宏关联逻辑类型和实际类型 Part 7</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">2.</strong> 生命周期</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../02_生命周期/Rust中的生命周期——从StrSplit实例说开去/Rust中的生命周期——从StrSplit实例说开去.html"><strong aria-hidden="true">2.1.</strong> Rust中的生命周期——从StrSplit实例说开去</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/与ChatGPT深度对话来学Rust生命周期/与ChatGPT深度对话来学Rust生命周期.html"><strong aria-hidden="true">2.2.</strong> 与ChatGPT深度对话来学Rust生命周期</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——early_bound与late_bound（1）/进击的Rust生命周期——early_bound与late_bound（1）.html"><strong aria-hidden="true">2.3.</strong> 进击的Rust生命周期——early_bound与late_bound（1）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——early_bound与late_bound（2）/进击的Rust生命周期——early_bound与late_bound（2）.html"><strong aria-hidden="true">2.4.</strong> 进击的Rust生命周期——early_bound与late_bound（2）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——一力降十会的MIR（1）/进击的Rust生命周期——一力降十会的MIR（1）.html"><strong aria-hidden="true">2.5.</strong> 进击的Rust生命周期——一力降十会的MIR（1）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/进击的Rust生命周期——一力降十会的MIR（2）/进击的Rust生命周期——一力降十会的MIR（2）.html"><strong aria-hidden="true">2.6.</strong> 进击的Rust生命周期——一力降十会的MIR（2）</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/Common_Rust_Lifetime_Misconceptions/Common_Rust_Lifetime_Misconceptions.html"><strong aria-hidden="true">2.7.</strong> Common Rust Lifetime Misconceptions</a></li><li class="chapter-item expanded "><a href="../../02_生命周期/Rust生命周期常见误区/Rust生命周期常见误区.html"><strong aria-hidden="true">2.8.</strong> 译：Rust生命周期常见误区</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">3.</strong> 无畏并发</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../05_无畏并发/简单写个Rust无锁队列/简单写个Rust无锁队列.html"><strong aria-hidden="true">3.1.</strong> 简单写个Rust无锁队列</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/进击的Rust多线程——混合自旋锁/进击的Rust多线程——混合自旋锁.html"><strong aria-hidden="true">3.2.</strong> 进击的Rust多线程——混合自旋锁</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/An_unsafe_tour_of_Rust's_Send_and_Sync/An_unsafe_tour_of_Rust's_Send_and_Sync.html"><strong aria-hidden="true">3.3.</strong> An unsafe tour of Rust's Send and Sync</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/进击的Rust多线程——Send与Sync/进击的Rust多线程——Send与Sync.html"><strong aria-hidden="true">3.4.</strong> 进击的Rust多线程——Send与Sync</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/进击的Rust多线程——离经叛道的PhantomData/进击的Rust多线程——离经叛道的PhantomData.html"><strong aria-hidden="true">3.5.</strong> 进击的Rust多线程——离经叛道的PhantomData</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/Rust_Async_Pin概念解析/Rust_Async_Pin概念解析.html"><strong aria-hidden="true">3.6.</strong> Rust Async: Pin概念解析</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/Rust和C++的并发库对比/Rust和C++的并发库对比.html"><strong aria-hidden="true">3.7.</strong> 译：Rust 和 C++ 的并发库对比</a></li><li class="chapter-item expanded "><a href="../../05_无畏并发/Rust原子类型和内存排序/Rust原子类型和内存排序.html"><strong aria-hidden="true">3.8.</strong> Rust原子类型和内存排序</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">4.</strong> 网络编程</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../06_网络编程/从编解码层面理解WebSocket_手写一个WebSocket/从编解码层面理解WebSocket_手写一个WebSocket.html"><strong aria-hidden="true">4.1.</strong> 从编解码层面理解WebSocket 手写一 个WebSocket</a></li><li class="chapter-item expanded "><a href="../../06_网络编程/透过Rust探索系统的本原：网络篇/透过Rust探索系统的本原：网络篇.html"><strong aria-hidden="true">4.2.</strong> 透过Rust探索系统的本原：网络篇</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">5.</strong> 轮子系列</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../07_轮子系列/700行Rust写一个内存分配器/700行Rust写一个内存分配器.html"><strong aria-hidden="true">5.1.</strong> 700行Rust写一个内存分配器</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/Rust：网络库的实现思路/Rust：网络库的实现思路.html"><strong aria-hidden="true">5.2.</strong> Rust：网络库的实现思路</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/Rust异步运行时基础部件/Rust异步运行时基础部件.html"><strong aria-hidden="true">5.3.</strong> Rust异步运行时基础部件</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/使用Rust+epoll编写异步IO框架/使用Rust+epoll编写异步IO框架（1）.html"><strong aria-hidden="true">5.4.</strong> 使用Rust+epoll编写异步IO框架（1）</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/使用Rust+epoll编写异步IO框架/使用Rust+epoll编写异步IO框架（2）.html"><strong aria-hidden="true">5.5.</strong> 使用Rust+epoll编写异步IO框架（2）</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/使用Rust+epoll编写异步IO框架/使用Rust+epoll编写异步IO框架（3）.html"><strong aria-hidden="true">5.6.</strong> 使用Rust+epoll编写异步IO框架（3）</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day1.html"><strong aria-hidden="true">5.7.</strong> 用rust从零开发一套web框架：day1</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day2.html"><strong aria-hidden="true">5.8.</strong> 用rust从零开发一套web框架：day2</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day3.html"><strong aria-hidden="true">5.9.</strong> 用rust从零开发一套web框架：day3</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day4.html"><strong aria-hidden="true">5.10.</strong> 用rust从零开发一套web框架：day4</a></li><li class="chapter-item expanded "><a href="../../07_轮子系列/用rust从零开发一套web框架/用rust从零开发一套web框架：day5.html"><strong aria-hidden="true">5.11.</strong> 用rust从零开发一套web框架：day5</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">6.</strong> 奇技淫巧</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../08_奇技淫巧/Copy-On-Write是不是优化？/Copy-On-Write是不是优化？.html"><strong aria-hidden="true">6.1.</strong> 译：Copy-On-Write是不是优化？</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/揭秘神奇的Rust_Axum风格的函数实现/揭秘神奇的Rust_Axum风格的函数实现.html"><strong aria-hidden="true">6.2.</strong> 译：揭秘神奇的 Rust Axum 风格的函数实现</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/“变长参数”函数与回调/“变长参数”函数与回调.html"><strong aria-hidden="true">6.3.</strong> “变长参数”函数与回调</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/Rust字符串格式化的幕后：format_args!()/Rust字符串格式化的幕后：format_args!().html"><strong aria-hidden="true">6.4.</strong> 译：Rust字符串格式化的幕后：format_args!()</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/给Rust带来一点C++特产/给Rust带来一点C++特产.html"><strong aria-hidden="true">6.5.</strong> 给Rust带来一点C++特产</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/一步步实现_Rust_Bevy_ECS_的_System_简化版本/一步步实现_Rust_Bevy_ECS_的_System_简化版本.html"><strong aria-hidden="true">6.6.</strong> 一步步实现 Rust Bevy ECS 的 System 简化版本</a></li><li class="chapter-item expanded "><a href="../../08_奇技淫巧/Exploring_Design_Patterns_in_Rust_with_Algorithmic_Trading_Examples/Exploring_Design_Patterns_in_Rust_with_Algorithmic_Trading_Examples.html"><strong aria-hidden="true">6.7.</strong> Exploring Design Patterns in Rust with Algorithmic Trading Examples</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">7.</strong> 源码分析</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../09_源码分析/Rust并发：bytes源码分析/Rust并发：bytes源码分析.html"><strong aria-hidden="true">7.1.</strong> Rust并发：bytes源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust并发：标准库Arc源码分析/Rust并发：标准库Arc源码分析.html"><strong aria-hidden="true">7.2.</strong> Rust并发：标准库Arc源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust并发：标准库sync_Once源码分析/Rust并发：标准库sync_Once源码分析.html"><strong aria-hidden="true">7.3.</strong> Rust并发：标准库sync::Once源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust源码阅读：引用计数Rc/Rust源码阅读：引用计数Rc.html"><strong aria-hidden="true">7.4.</strong> Rust源码阅读：引用计数Rc</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust源码阅读：Cell、RefCell与内部可变性/Rust源码阅读：Cell、RefCell与内部可变性.html"><strong aria-hidden="true">7.5.</strong> Rust源码阅读： Cell、RefCell与内部可变性</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/关于_Rust_的_UnsafeCell、Cell_与_RefCell/关于_Rust_的_UnsafeCell、Cell_与_RefCell.html"><strong aria-hidden="true">7.6.</strong> 关于 Rust 的 UnsafeCell、Cell 与 RefCell</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust_Async_async-stream源码分析/Rust_Async_async-stream源码分析.html"><strong aria-hidden="true">7.7.</strong> Rust Async: async-stream源码分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/走进Tokio的异步世界/走进Tokio的异步世界.html"><strong aria-hidden="true">7.8.</strong> 走进 Tokio 的异步世界</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/tokio.rs_runtime的实现/tokio.rs_runtime的实现.html"><strong aria-hidden="true">7.9.</strong> tokio.rs runtime 的实现</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Tokio_internals/Tokio_internals.html"><strong aria-hidden="true">7.10.</strong> Tokio internals</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Tokio_internals/译文：Tokio內部机制.html"><strong aria-hidden="true">7.11.</strong> 译：Tokio 内部机制</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Rust_Axum_HTTP_框架的架构分析/Rust_Axum_HTTP_框架的架构分析.html"><strong aria-hidden="true">7.12.</strong> Rust Axum HTTP 框架的架构分析</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/安利一个Rust_Game_Engine：Bevy--ECS部分/安利一个Rust_Game_Engine：Bevy--ECS部分.html"><strong aria-hidden="true">7.13.</strong> 安利一个Rust Game Engine：Bevy--ECS部分</a></li><li class="chapter-item expanded "><a href="../../09_源码分析/Tokio_解析之任务调度/Tokio_解析之任务调度.html"><strong aria-hidden="true">7.14.</strong> Tokio 解析之任务调度</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">8.</strong> 生态观察</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../11_生态观察/Rust_web_frameworks_have_subpar_error_reporting/Rust_web_frameworks_have_subpar_error_reporting.html"><strong aria-hidden="true">8.1.</strong> Rust web frameworks have subpar error reporting</a></li><li class="chapter-item expanded "><a href="../../11_生态观察/SeaORM：要做Rust版本的ActiveRecord/SeaORM：要做Rust版本的ActiveRecord.html"><strong aria-hidden="true">8.2.</strong> SeaORM：要做Rust版本的ActiveRecord</a></li></ol></li><li class="chapter-item expanded "><a href="../../empty.html"><strong aria-hidden="true">9.</strong> 死灵终极</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_总述.html"><strong aria-hidden="true">9.1.</strong> 译：Learn Rust the Dangerous Way 总述</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_0.html"><strong aria-hidden="true">9.2.</strong> 译：Learn Rust the Dangerous Way 0</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_1.html"><strong aria-hidden="true">9.3.</strong> 译：Learn Rust the Dangerous Way 1</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_2.html"><strong aria-hidden="true">9.4.</strong> 译：Learn Rust the Dangerous Way 2</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_3.html"><strong aria-hidden="true">9.5.</strong> 译：Learn Rust the Dangerous Way 3</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_4.html"><strong aria-hidden="true">9.6.</strong> 译：Learn Rust the Dangerous Way 4</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Learn_Rust_the_Dangerous_Way_系列文章翻译/Learn_Rust_the_Dangerous_Way_系列文章翻译_5.html"><strong aria-hidden="true">9.7.</strong> 译：Learn Rust the Dangerous Way 5</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测（一）.html"><strong aria-hidden="true">9.8.</strong> Unsafe Rust 随堂小测（一）</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测（二）.html"><strong aria-hidden="true">9.9.</strong> Unsafe Rust 随堂小测（二）</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测（三）.html"><strong aria-hidden="true">9.10.</strong> Unsafe Rust 随堂小测（三）</a></li><li class="chapter-item expanded "><a href="../../12_死灵终极/Unsafe_Rust_随堂小测/Unsafe_Rust_随堂小测参考答案.html"><strong aria-hidden="true">9.11.</strong> Unsafe Rust 随堂小测参考答案</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky bordered">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">Rust 优秀博文</h1>

                    <div class="right-buttons">
                        <a href="../../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="数据库表达式执行的黑魔法用-hrtb-写-bound-part-2"><a class="header" href="#数据库表达式执行的黑魔法用-hrtb-写-bound-part-2">数据库表达式执行的黑魔法：用 HRTB 写 bound (Part 2)</a></h1>
<p>作者：<a href="https://www.zhihu.com/people/skyzh">迟策</a></p>
<p>原载：<a href="https://zhuanlan.zhihu.com/p/461405621">https://zhuanlan.zhihu.com/p/461405621</a></p>
<p>上篇：<a href="https://zhuanlan.zhihu.com/p/460977012">数据库表达式执行的黑魔法：用 Rust 做类型体操 (Part 1)</a></p>
<p>下篇：<a href="https://zhuanlan.zhihu.com/p/461657165">数据库表达式执行的黑魔法：用 Rust 做类型体操 (Part 3 &amp; 4)</a></p>
<h2 id="day-2-scalar-与-scalarref"><a class="header" href="#day-2-scalar-与-scalarref">Day 2: <code>Scalar</code> 与 <code>ScalarRef</code></a></h2>
<p><img src="assets/002/0010.webp" alt="" /></p>
<p>如果您想直接看最终实现，可以直接跳转到 <a href="https://link.zhihu.com/?target=https%3A//github.com/skyzh/type-exercise-in-rust/tree/master/archive/day2">Day 2 对应的源代码</a>.</p>
<h3 id="目标"><a class="header" href="#目标">目标</a></h3>
<p>回到之前向量化执行的代码：</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>fn eval_binary&lt;I: Array, O: Array&gt;(i1: I, i2: I) -&gt; O {
    assert_eq!(i1.len(), i2.len(), &quot;size mismatch&quot;);
    let mut builder = O::Builder::with_capacity(i1.len());
    for (i1, i2) in i1.iter().zip(i2.iter()) {
       builder.push(sql_func(i1, i2));
    }
    builder.finish()
}
<span class="boring">}
</span></code></pre></pre>
<p>思考一下 <code>sql_func</code> 的函数签名应该是什么样？我们可以从 primitive type 和 string 两方面去考虑。</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>// 两数相加
fn sql_add(a: i32, b: i32) -&gt; i32 { a + b }

// 字符串拼接
fn concat(a: &amp;str, b: &amp;str) -&gt; String { a.to_string() + b }
<span class="boring">}
</span></code></pre></pre>
<p>我们会发现一件神奇的事情：<code>sql_func</code> 通常来说会接收两个引用，然后产生一个有所有权的类型，比如 <code>String</code>。但是，<code>builder.push</code> 接收的是一个引用类型 <code>&amp;str</code>。</p>
<pre><code class="language-text">builder.push(sql_func(i1, i2).xxx() /* do some cast? */);
</code></pre>
<p>怎么在泛型函数里面转换这两个类型呢？这就需要我们引入新的 trait 来解决这个问题。</p>
<h3 id="实现-scalar"><a class="header" href="#实现-scalar">实现 <code>Scalar</code></a></h3>
<p>有了上次实现 <code>Array</code> 和 <code>ArrayBuilder</code> 的经验，我们可以用 associated type 来关联 <code>Array</code> 和 <code>Scalar</code>两个类型。注意写 <code>ArrayType</code> 的 trait bound 的时候要指明“Scalar 的 Array 的 OwnedItem 是我自己”。</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>/// An owned single value.
///  
/// For example, `i32`, `String` both implements [`Scalar`].
pub trait Scalar: std::fmt::Debug + Clone + Send + Sync + 'static {
    /// The corresponding [`Array`] type.
    type ArrayType: Array&lt;OwnedItem = Self&gt;;
}

pub trait Array: Send + Sync + Sized + 'static {
    /// The owned item of this array.
    type OwnedItem: Scalar&lt;ArrayType = Self&gt;;
}
<span class="boring">}
</span></code></pre></pre>
<p>之后给各个类型都 impl <code>Scalar</code>，就没什么问题了。</p>
<h3 id="实现-scalarref"><a class="header" href="#实现-scalarref">实现 <code>ScalarRef</code></a></h3>
<p><code>ScalarRef</code> 表示一个 <code>Scalar</code> 对应的某个生命周期的引用类型。举例：</p>
<ul>
<li><code>i32</code> 是 <code>Scalar</code>, 也是 <code>ScalarRef</code>.</li>
<li><code>String</code> 是 <code>Scalar</code>, <code>&amp;'a str</code> 是 <code>ScalarRef&lt;'a&gt;</code>.</li>
</ul>
<p>我们先实现 <code>ScalarRef</code>，然后把 <code>Array</code>, <code>Scalar</code>, <code>ScalarRef</code> 三者关联起来。</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>/// A borrowed value.
///
/// For example, `i32`, `&amp;str` both implements [`ScalarRef`].
pub trait ScalarRef&lt;'a&gt;: std::fmt::Debug + Clone + Copy + Send + 'a {
    /// The corresponding [`Array`] type.
    type ArrayType: Array&lt;RefItem&lt;'a&gt; = Self&gt;;

    /// The corresponding [`Scalar`] type.
    type ScalarType: Scalar&lt;RefType&lt;'a&gt; = Self&gt;;

    /// Convert the reference into an owned value.
    fn to_owned_scalar(&amp;self) -&gt; Self::ScalarType;
}

pub trait Scalar: std::fmt::Debug + Clone + Send + Sync + 'static {
    /// The corresponding [`Array`] type.
    type ArrayType: Array&lt;OwnedItem = Self&gt;;

    /// The corresponding [`ScalarRef`] type.
    type RefType&lt;'a&gt;: ScalarRef&lt;'a, ScalarType = Self, ArrayType = Self::ArrayType&gt;
    where
        Self: 'a;

    /// Get a reference of the current value.
    fn as_scalar_ref(&amp;self) -&gt; Self::RefType&lt;'_&gt;;
}

/// [`Array`] is a collection of data of the same type.
pub trait Array: Send + Sync + Sized + 'static {
    /// The owned item of this array.
    type OwnedItem: Scalar&lt;ArrayType = Self&gt;;

    type RefItem&lt;'a&gt;: ScalarRef&lt;'a, ScalarType = Self::OwnedItem, ArrayType = Self&gt;;
}
<span class="boring">}
</span></code></pre></pre>
<p>接着对各个类型都实现 <code>ScalarRef</code>，即可通过 <code>Scalar::as_scalar_ref</code> 将一个 OwnedType 转换为 RefType。</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>/// Implement [`Scalar`] for `i32`. Note that `i32` is both [`Scalar`] and [`ScalarRef`].
impl Scalar for i32 {
    type ArrayType = I32Array;
    type RefType&lt;'a&gt; = i32;

    fn as_scalar_ref(&amp;self) -&gt; i32 {
        *self
    }
}

/// Implement [`ScalarRef`] for `i32`. Note that `i32` is both [`Scalar`] and [`ScalarRef`].
impl&lt;'a&gt; ScalarRef&lt;'a&gt; for i32 {
    type ArrayType = I32Array;
    type ScalarType = i32;

    fn to_owned_scalar(&amp;self) -&gt; i32 {
        *self
    }
}

/// Implement [`Scalar`] for `String`.
impl Scalar for String {
    type ArrayType = StringArray;
    type RefType&lt;'a&gt; = &amp;'a str;

    fn as_scalar_ref(&amp;self) -&gt; &amp;str {
        self.as_str()
    }
}

/// Implement [`ScalarRef`] for `&amp;str`.
impl&lt;'a&gt; ScalarRef&lt;'a&gt; for &amp;'a str {
    type ArrayType = StringArray;
    type ScalarType = String;

    fn to_owned_scalar(&amp;self) -&gt; String {
        self.to_string()
    }
}
<span class="boring">}
</span></code></pre></pre>
<h3 id="用-hrtb-表达-gat-类型相同"><a class="header" href="#用-hrtb-表达-gat-类型相同">用 HRTB 表达 GAT 类型相同</a></h3>
<p>一切都非常地顺利，于是我们来试着编译一下向量化函数：</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>fn sql_func&lt;'a, I: Array, O: Array&gt;(i1: I::RefItem&lt;'a&gt;, i2: I::RefItem&lt;'a&gt;) -&gt; O::OwnedItem {
    todo!()
}

fn eval_binary&lt;I: Array, O: Array&gt;(i1: I, i2: I) -&gt; O {
    assert_eq!(i1.len(), i2.len(), &quot;size mismatch&quot;);
    let mut builder = O::Builder::with_capacity(i1.len());
    for (i1, i2) in i1.iter().zip(i2.iter()) {
        match (i1, i2) {
            (Some(i1), Some(i2)) =&gt; {
                builder.push(Some(sql_func::&lt;I, O&gt;(i1, i2).as_scalar_ref()))
            }
            _ =&gt; builder.push(None),
        }
    }
    builder.finish()
}
<span class="boring">}
</span></code></pre></pre>
<p>编译器又一次无情打脸：</p>
<pre><code class="language-text">error[E0308]: mismatched types
  --&gt; archive/day2/src/array.rs:85:39
   |
85 |                     builder.push(Some(sql_func::&lt;I, O&gt;(i1, i2).as_scalar_ref()))
   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected array::Array::RefItem, found scalar::Scalar::RefType
   |
   = note: expected associated type `&lt;O as array::Array&gt;::RefItem&lt;'_&gt;`
              found associated type `&lt;&lt;O as array::Array&gt;::OwnedItem as scalar::Scalar&gt;::RefType&lt;'_&gt;`
</code></pre>
<p>这是怎么回事捏？为什么编译器说 <code>Array::RefItem</code> 和 <code>Scalar::RefType</code> 不是一个类型呢？</p>
<p>回顾之前我们写的所有 trait bound：</p>
<p>对于 <code>ScalarRef</code>，我们提供的类型信息是：</p>
<ul>
<li>
<p><code>type ArrayType: Array&lt;RefItem&lt;'a&gt; = Self&gt;;</code></p>
</li>
<li>
<ul>
<li>ScalarRef 的 Array 的 RefItem 是我自己。</li>
</ul>
</li>
<li>
<p><code>type ScalarType: Scalar&lt;RefType&lt;'a&gt; = Self&gt;;</code></p>
</li>
<li>
<ul>
<li>ScalarRef 的 Scalar 是我自己。</li>
</ul>
</li>
</ul>
<p>对于 <code>Scalar</code>，我们提供的类型信息是：</p>
<ul>
<li>
<p><code>type ArrayType: Array&lt;OwnedItem = Self&gt;;</code></p>
</li>
<li>
<ul>
<li>Scalar 的 Array 的 OwnedItem 是我自己。</li>
</ul>
</li>
<li>
<p><code>type RefType&lt;'a&gt;: ScalarRef&lt;'a, ScalarType = Self, ArrayType = Self::ArrayType&gt;</code></p>
</li>
<li>
<ul>
<li>Scalar 的 RefType 的 ScalarType 是我自己</li>
<li>Scalar 的 RefType 的 ArrayType 是我的 ArrayType</li>
</ul>
</li>
</ul>
<p>对于 <code>Array</code>, 我们提供的类型信息是：</p>
<ul>
<li>
<p><code>type OwnedItem: Scalar&lt;ArrayType = Self&gt;;</code></p>
</li>
<li>
<ul>
<li>Array 的 OwnedItem 的 Array 是我自己。</li>
</ul>
</li>
<li>
<p><code>type RefItem&lt;'a&gt;: ScalarRef&lt;'a, ScalarType = Self::OwnedItem, ArrayType = Self&gt;;</code></p>
</li>
<li>
<ul>
<li>Array 的 RefItem 的 ScalarType 是我的 OwnedItem，Array 的 RefItem 的 ArrayType 是我自己。</li>
</ul>
</li>
</ul>
<p>这么看了一圈，唯独缺了编译器提示的这一条信息：</p>
<pre><code class="language-text">note: expected associated type `&lt;O as array::Array&gt;::RefItem&lt;'_&gt;`
              found associated type `&lt;&lt;O as array::Array&gt;::OwnedItem as scalar::Scalar&gt;::RefType&lt;'_&gt;`
</code></pre>
<p>我们没有证明 Array 的 RefItem 都是 Array 的 OwnedItem 的 RefType！</p>
<p><img src="assets/002/0020.png" alt="" /></p>
<p>这个 trait bound 应该怎么写在 Array 上呢？</p>
<ul>
<li><code>RefItem&lt;'a&gt;</code>, <code>RefType&lt;'a&gt;</code> 是一个 GAT</li>
<li><code>Array::RefItem&lt;'a&gt; == Array::OwnedItem::RefType&lt;'a&gt;</code> 要成立</li>
<li>Array 自己没有生命周期，这个 <code>'a</code> 从哪里来？</li>
</ul>
<p>经过一番思考，<code>Array::RefItem&lt;'a&gt; == Array::OwnedItem::RefType&lt;'a&gt;</code> 这个性质应该<strong>对任意生命周期都成立</strong>。因此，我们可以用 <a href="https://link.zhihu.com/?target=https%3A//doc.rust-lang.org/nomicon/hrtb.html">HRTB</a> Higher-Rank Trait Bounds 来写。</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>pub trait Array: Send + Sync + Sized + 'static
where
    for&lt;'a&gt; Self::OwnedItem: Scalar&lt;RefType&lt;'a&gt; = Self::RefItem&lt;'a&gt;&gt;,
{
    /* ... */
}
<span class="boring">}
</span></code></pre></pre>
<p>这样就可以表达两个 GAT 之间的关系了。</p>
<h3 id="为-primitivearray-加上新的-trait-bound"><a class="header" href="#为-primitivearray-加上新的-trait-bound">为 PrimitiveArray 加上新的 trait bound</a></h3>
<p>试着编译一下代码，又被编译器无情打脸：</p>
<pre><code class="language-text">error[E0271]: type mismatch resolving `&lt;T as scalar::Scalar&gt;::ArrayType == PrimitiveArray&lt;T&gt;`
  --&gt; archive/day2/src/array/primitive_array.rs:46:20
   |
46 |     type Builder = PrimitiveArrayBuilder&lt;T&gt;;
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `PrimitiveArray`, found associated type
   |
   = note:       expected struct `PrimitiveArray&lt;T&gt;`
           found associated type `&lt;T as scalar::Scalar&gt;::ArrayType`
   = help: consider constraining the associated type `&lt;T as scalar::Scalar&gt;::ArrayType` to `PrimitiveArray&lt;T&gt;`
   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
</code></pre>
<p><em>注：<code>Scalar</code></em> <em>相关的编译错误其实之前就应该出现，不过为了文章的编排顺序，我们在这里和 HRTB bound 一起讲。</em></p>
<p>这个错误其实很好理解：在我们的系统里，可以有 <code>PrimitiveArray&lt;u8&gt;</code>, 可以有 <code>PrimitiveArray&lt;i64&gt;</code>，但只有后者是实现了 Array 的，前者没有。所以，在 <code>impl PrimitiveArray&lt;T&gt;</code> 的时候，也要对相关的 trait 做一些限制，只对我们支持的类型 impl。因此，要加上 <code>Scalar</code> 和 <code>ScalarRef</code> 的两个 bound。由于 <code>Array</code> 本身没有生命周期，因此要用 HRTB bound 表达当前 Array 产生的所有 <code>ScalarRef</code> 和 <code>Scalar</code>, <code>Array</code> 都有对应关系。</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>impl&lt;T&gt; Array for PrimitiveArray&lt;T&gt;
where
    T: PrimitiveType,
    T: Scalar&lt;ArrayType = Self&gt;,
    for&lt;'a&gt; T: ScalarRef&lt;'a, ScalarType = T, ArrayType = Self&gt;,
<span class="boring">}
</span></code></pre></pre>
<p>加完之后，编译器又报了一个错：</p>
<pre><code class="language-text">error[E0271]: type mismatch resolving `for&lt;'a&gt; &lt;T as scalar::Scalar&gt;::RefType&lt;'a&gt; == T`
  --&gt; archive/day2/src/array/primitive_array.rs:51:22
   |
42 | impl&lt;T&gt; Array for PrimitiveArray&lt;T&gt;
   |      - this type parameter
...
51 |     type OwnedItem = T;
   |                      ^ expected type parameter `T`, found associated type
   |
   = note: expected type parameter `T`
             found associated type `&lt;T as scalar::Scalar&gt;::RefType&lt;'_&gt;`
note: required by a bound in `array::Array::OwnedItem`
  --&gt; archive/day2/src/array.rs:23:37
   |
23 |     for&lt;'a&gt; Self::OwnedItem: Scalar&lt;RefType&lt;'a&gt; = Self::RefItem&lt;'a&gt;&gt;,
   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `array::Array::OwnedItem`
...
31 |     type OwnedItem: Scalar&lt;ArrayType = Self&gt;;
   |          --------- required by a bound in this
help: consider further restricting type parameter `T`
   |
46 |     for&lt;'a&gt; T: ScalarRef&lt;'a, ScalarType = T, ArrayType = Self&gt;, T: scalar::Scalar&lt;RefType&lt;'_&gt; = T&gt;
   |                                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
</code></pre>
<p>这该怎么理解捏？</p>
<p>用 <code>i32</code> 来举例，编译器推导不出来 <code>i32::RefType == i32 (OwnedType)</code>。这个报错很明显和我们预想实现的不太一样：RefType 怎么可能等于 OwnedType？感觉像是报错没报对地方。</p>
<p>稍作思考，为什么这个地方 <code>OwnedType</code> 和 <code>RefType</code> 关联起来了？因为 <code>i32</code> 既是 <code>ScalarRef</code>, 也是 <code>Scalar</code>。逆向思维一下，这个报错可能实际上是由：</p>
<pre><code class="language-text">&lt;i32 as Scalar&gt;::RefType ?= i32 (Array::RefItem)`
</code></pre>
<p>引起的。</p>
<p>因此，我们只需要把 PrimitiveArray 的 <code>for&lt;'a&gt; T: Scalar&lt;RefType&lt;'a&gt; = T&gt;</code> 的 bound 就上就行了，以满足 Array 的 <code>for&lt;'a&gt; Self::OwnedItem: Scalar&lt;RefType&lt;'a&gt; = Self::RefItem&lt;'a&gt;&gt;</code>。</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>impl&lt;T&gt; Array for PrimitiveArray&lt;T&gt;
where
    T: PrimitiveType,
    T: Scalar&lt;ArrayType = Self&gt;,
    for&lt;'a&gt; T: ScalarRef&lt;'a, ScalarType = T, ArrayType = Self&gt;,
    for&lt;'a&gt; T: Scalar&lt;RefType&lt;'a&gt; = T&gt;,
{
    // ...
}
<span class="boring">}
</span></code></pre></pre>
<p><code>PrimitiveArray</code> 和 <code>PrimitiveArrayBuilder</code> 有了这四个 bound 之后，编译就能通过了。day 2 顺利结束！您可以在<a href="https://link.zhihu.com/?target=https%3A//github.com/skyzh/type-exercise-in-rust">type-exercise-in-rust</a>中围观整个系统的实现。</p>
<p>上篇：<a href="https://zhuanlan.zhihu.com/p/460977012">数据库表达式执行的黑魔法：用 Rust 做类型体操 (Part 1)</a></p>
<p>下篇：<a href="https://zhuanlan.zhihu.com/p/461657165">数据库表达式执行的黑魔法：用 Rust 做类型体操 (Part 3 &amp; 4)</a></p>
<p><em>（系列文章持续更新中，下一次更新时间看心情）</em></p>
<p>编辑于 2022-02-02 16:17</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：GAT实现引用类型关联_Part_1.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>

                            <a rel="next" href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用Rust做类型体操之用宏展开重复代码_Part_3_&amp;_4.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：GAT实现引用类型关联_Part_1.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>

                    <a rel="next" href="../../01_类型系统/数据库表达式执行的黑魔法：用Rust做类型体操/数据库表达式执行的黑魔法：用Rust做类型体操之用宏展开重复代码_Part_3_&amp;_4.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>




        <script type="text/javascript">
            window.playground_copyable = true;
        </script>


        <script src="../../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../searcher.js" type="text/javascript" charset="utf-8"></script>

        <script src="../../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->


    </body>
</html>
